package com.coderush.admin.core.interceptors;

import com.alibaba.fastjson2.JSON;
import com.coderush.admin.core.component.JwtUtil;
import com.coderush.admin.core.component.RedisClient;
import com.coderush.admin.core.config.JwtConfig;
import com.coderush.admin.core.response.Result;
import com.coderush.admin.core.utils.UserContext;
import com.coderush.admin.core.utils.UserContextModel;
import com.coderush.admin.sys.consts.EmployeeCacheKey;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.io.PrintWriter;

/**
 * 认证拦截器
 *
 */
@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private JwtConfig jwtConfig;
    @Resource
    private RedisClient redisClient;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 获取请求地址
        String requestPath = request.getRequestURI();
        log.info("认证拦截器 - 请求地址：{}", requestPath);
        // 放行不需要认证的接口
        if (jwtConfig.getExcludePaths().contains(requestPath)) {
            return true;
        }

        // 获取访问 Token
        String accessToken = request.getHeader("Authorization");
        if (accessToken == null || !accessToken.startsWith("Bearer ")) {
            sendAuthFailed(response, "缺少访问Token, 请重新登录");
            return false;
        }
        accessToken = accessToken.substring(7); // 去掉 Bearer 前缀

        // 校验 Token
        if (!jwtUtil.validateToken(accessToken)) {
            sendAuthFailed(response, "Token无效, 请重新登录");
            return false;
        }

        // 检查 Token 是否已过期
        if (jwtUtil.isTokenExpired(accessToken)) {
            sendAuthFailed(response, "Token已过期, 请重新登录");
            return false;
        }

        // 从Redis缓存中获取用户登录信息
        UserContextModel userContextModel = redisClient.getKVForType(EmployeeCacheKey.EMPLOYEE_LOGIN_TOKEN_PREFIX + accessToken, UserContextModel.class);
        if (userContextModel == null) {
            sendAuthFailed(response, "用户信息已过期, 请重新登录");
            return false;
        }
        // 保存用户信息
        userContextModel.setAccessToken(accessToken); // 保存访问Token
        UserContext.saveUser(userContextModel);

        return true;
    }

    /**
     * 认证失败，返回错误信息
     * HTTP 状态码 401 表示 Unauthorized（未授权）。
     * 当客户端尝试访问一个受保护的资源，但未提供有效的身份验证凭据（如用户名、密码、Token 等），服务器就会返回 401 Unauthorized 状态码。
     */
    private void sendAuthFailed(HttpServletResponse response, String message) throws IOException {
        Result<Object> result = Result.buildFail(401, message);
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(JSON.toJSONString(result));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {writer.close();}
        }
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 移除用户
        UserContext.removeUser();
    }
}